//
// Part1-2 作业
//
// 1. 请说出下列最终执行结果，并解释为什么?
//
    var a = [];
    for(var i = 0; i < 10; i++) {
        a[i] = function() {
            console.log(i)
        }
    }
    a[6]()
// 1.10  因为代码中存在两个全局变量，数组a与循环变量i，
// 数组中每个元素保存着一个匿名函数，该函数引用了循环变量i。
// 在调用a[0]() 时，i值是已经循环10次后的变量值10.
// 如果想要在函数体内保存每次循环时的值，可以用即时调用函数表达式或使用let块级循环作用域。

// 2. 请说出此案列最终执行结果，并解释为什么?
//
    var tmp = 123;
    if (true) {
        console.log(tmp);
        let tmp;
    }
    // 2. 报错，只要块级作用域内存在let命令，
    // 它所声明的变量就“绑定”这个区域，不再受外部的影响。
    // 总之，在代码块内，使用let命令声明变量之前，该变量都是不可用的，
    // 尽管代码块外也存在相同全局变量

// 3. 结合ES6语法，用最简单的方式找出数组中的最小值
//
    var arr = [12, 34, 32, 89, 4]

    // arr.sort((a,b)=> {
    //     return a-b
    // })[0]
    arr = Math.min(...[arr])

// 4. 请详细说明var、let、const三种声明变量的方式之间的具体差别
// var 可以重复声明，存在变量提升
// let 声明的变量只有在代码块内才有效， 不能重复声明
// const 声明的变量只有在代码块内才有效， 不能重复声明 如果是基本引用类型不能改变他的值

// 5. 请说出下列代码最终输出结果，并解释为什么？
//
    var a = 10;
    var obj = {
        a: 20,
        fn() {
            setTimeout(() => {
                console.log(this.a)
            })
        }
    }
    obj.fn()
// 输出20
// 首先通过obj调用fn函数，在fn函数内部this的指向是obj。
// 而setTimeout中的箭头函数是没有this的指向的，里面的this依赖于上层作用域中的this,即obj.

// 6. 简述Symbol类型的用途
//  Symbol 唯一的用途就是标识对象属性，表明对象支持的功能。 相比于字符属性名，Symbol 的区别在于唯一，可避免名字冲突。

// 7. 说说什么是浅拷贝，什么是深拷贝？
//  浅拷贝对基本类型是复制他的值，对基本引用类型是复制他的指针，如果更改会改变指向他的内容里面的值
//  深拷贝对基本类型是复制他的值，对基本引用类型是来存放他的指针的内容，如果更改会不会改变指向他的内容里面的值

// 8. 请简述TypeScript与JavaScript之间的关系？
// 　TypeScript是Javascript的超集，实现以面向对象编程的方式使用Javascript。当然最后代码还是编译为Javascript。
　
// 9. 请谈谈你所认为的typescript优缺点
    //  优点：
    // （1）增强代码的可读性和可维护性，强类型的系统相当于最好的文档，在编译时即可发现大部分的错误，增强编辑器的功能。
    // （2）包容性，js文件可以直接改成 ts 文件，不定义类型可自动推论类型，可以定义几乎一切类型，ts 编译报错时也可以生成 js 文件，兼容第三方库，即使不是用ts编写的
    // （3）有活跃的社区，大多数的第三方库都可提供给 ts 的类型定义文件，完全支持 es6 规范
    //  缺点：
    // （1）增加学习成本，需要理解接口（Interfaces）和泛型（Generics），类（class），枚举类型（Enums）
    // （2）短期增加开发成本，增加类型定义，但减少维护成本
    // （3）ts 集成到构建流程需要一定的工作量
    // （4）和有些库结合时不是很完美

// 10. 描述引用计数的工作原理和优缺点
// 引用计数法对每一个对象保存一个整型的引用计数器属性。用于记录对象被引用的情况。
// 对于一个对象A，只要有任何一个对象引用了A，则A的引用计数器就加1；当引用失效时，引用计数器就减1。只要对象的引用计数器的值为0，即表示对象A不能在被使用，可进行回收。
// 优点：实现简单，垃圾对象便于辨识；判定效率高，回收没有延迟性。
// 缺点：（1）他需要单独的字段存储计数器，这样的做法增加了存储空间的开销。
//      （2）每次赋值都需要更新计数器，伴随着加法和减法操作，这增加了时间开销。
//      （3）引用计数器还有一个严重的问题，即无法处理循环引用的问题，这是一条致命的缺陷
//
// 11. 描述标记整理算法的工作流程
//  不直接对可回收对象进行清理，而是让所有可用的对象都向一端移动。然后直接清理非活动对象的内存。


// 12.描述V8中新生代存储区垃圾回收的流程
//  分为新生代和老生代
//  新生代空间又分为两个空间：from空间和to空间。
//  当from空间被沾满时，启动GC算法。
//  1、将存活的对象从from空间转移到to空间。
//  2、清空from空间
//  3、from space 与 to space 互换
//  4、完成一次新生代GC把不可以回收的放进老生代去，把可以回收的清理，并整理当前的存放的位置
//  在老生代区也是如此，不断的整理存放位置和释放可以回收的内容

// 13. 描述增量标记算法在何时使用及工作原理
// 将一整段垃圾回收操作分成几个小段
// 垃圾回收与程序执行交替完成
// 程序执行一段时间后，产生垃圾对象，开始遍历对象进行标记，第一次标记可能就标记第一层活动对象，第二次标记所有活动对象，最后对空间进行回收。
